home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
By Popular Request 2.0
/
By Popular Request 2.0 (Arsenal Computer).ISO
/
amiga_6
/
val-2_3.lha
/
Val.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-04-27
|
42KB
|
1,886 lines
/*
* Copyright (C) 1988 Andrew Kemmis
*
* All Rights Reserved
*
* Date: Jan 1988
*/
#include <ak/stdak.h>
#include <ak/debug.h>
char Program_name[] = "Val";
int Version = 2;
int MinorVer = 3;
char Date[] = "Dec 1993";
char CRDate[] = "1988-93";
#include <ak/err.h>
#include <ak/pool.h>
#include <ak/dev.h>
#include <ak/dos.h>
#include <intuition/intuitionbase.h>
#include "val.h"
#include "val.qi"
#define ULONGS(l) ((ulong)(l)*(ulong)sizeof(ulong))
#define ZAlloc(a) PoolAlloc((a), sizeof(*(a)), &GenPoolKey)
#define LAlloc(a,n,z) { if (!Seek)\
PoolAlloc((a), ULONGS(n), &GenPoolKey);\
else\
(char *)(a) = AllocMem(ULONGS(n), 0L);\
}
#define ULONGMAX 4294967295
extern char *strchr();
extern char *strrchr();
extern int strlen();
extern int strcmp();
extern int sscanf();
int cli;
struct IBASE *IBASE = (struct IBASE *)NULL;
Static int FileSystem;
#define IS_OFS 0
#define IS_FFS 1
Static char StrRoot[] = "Root";
Static char StrBitMap[] = "BitMap";
Static char StrEtc[] = "Dir,Fil,Lnk";
Static char StrDir[] = "Dir";
Static char StrFil[] = "Fil";
Static char StrExt[] = "Ext";
Static char StrDat[] = "Dat";
Static char StrSoftLnk[] = "SoftLnk";
Static char StrDirLnk[] = "DirLnk";
Static char StrFilLnk[] = "FilLnk";
Static char StrNextD[] = "NextDat";
Static char StrChain[] = "HashChain";
Static char StrNext[] = "Next";
Static char StrPrev[] = "Prev";
Static char StrHuh[] = "Unknown";
Static struct AkDevStuff Stuff = DEVSTUFFINIT;
Static uchar *Buffer;
Static long Dev = -1;
Static struct Names RootName =
{ (struct Names *)NULL, (struct Names *)NULL, ULONGMAX, };
Static struct Links
{ ushort type;
ulong block;
ulong prev;
ulong next;
struct Links *another;
} *LinkHead, *LinkMaybe;
Static uchar *FName;
Static int Inhibited = 0;
Static struct PoolKey BufPoolKey;
Static struct PoolKey GenPoolKey;
Static struct PoolKey ZerPoolKey;
Static ulong ReadCount = 0;
Static struct Info *LastInfo;
Static ulong LastBlk;
Static uchar *MyBitMap;
Static ulong ReadSmall = 0;
Static ulong ReadLarge = 0;
Static ulong ReadLNum = 0;
Static ulong HitSmall = 0;
Static ulong HitLarge = 0;
Static ulong MicSta;
Static ulong MicFin;
Static ulong MicCode;
Static ulong MicRead;
#define BMAP_TST(n) (MyBitMap[(n)>>3]&(1<<((n)&7)))
#define BMAP_SET(n) (MyBitMap[(n)>>3]|=(1<<((n)&7)))
Static Copy(d, s, l, siz)
REG char *d;
REG char *s;
REG ulong l;
REG int siz;
{
REG ulong len = l * (ulong)siz;
DBGS(">C");
while (len--)
*(d++) = *(s++);
DBGS("<C");
}
Static Get(Rem, num)
REG struct Info *Rem;
REG ulong num;
{
DBGS(">G");
if ((Rem - InfoList) >= MaxDepth)
MyError(ERR_TOODEEP, MaxDepth);
getblok(num + Stuff.Info.Begin, Rem);
DBGS("<G");
}
Static LONG DevRead(num, buf, size)
REG ulong num;
REG ulong *buf;
REG LONG size;
{
REG LONG ret;
REG int retry = Retries + 1;
DBGS(">DR");
while (retry-- && (ret = AkDevRead(num, buf, &Stuff, size)))
;
if (ret && FailReq)
{ if (!akrequester("Disk Read Error", "Continue", "Abort"))
{ puts("Aborted at users request on Read Error");
Cleanup();
}
}
DBGS("<DR");
return(ret);
}
Static int DoCache = !0;
#define CACHE_INVALID -7
Static LONG CacheRead(num, buf)
REG ulong num;
REG ulong **buf;
{
static ulong cache0 = CACHE_INVALID;
static ulong cache1 = CACHE_INVALID;
static ulong cache2 = CACHE_INVALID;
REG LONG ret = 0;
DBGS(">CR");
*buf = (ulong *)Buffer;
if (Cache == 1)
ret = DevRead(num, *buf, BLOCK_SIZE);
else
{ if (num == cache0 || num == (cache0 + 1) || (cache1 <= num && num <= cache2))
{ if (StatCache)
MicSta = IBASE->Micros;
if (num == (cache0+1))
*buf = (ulong *)&Buffer[BLOCK_SIZE];
else
if (num != cache0)
*buf = (ulong *)&Buffer[BLOCK_SIZE*(2 + num - cache1)];
if (StatCache)
MicFin = IBASE->Micros;
if (StatCache)
{ if (num == cache0 || num == (cache0+1))
HitSmall++;
else
HitLarge++;
if (MicSta > MicFin)
MicFin += 1000000;
MicCode += (MicFin - MicSta);
}
if (DebugCache)
{ if (num == cache0)
printf("Hit at :0\n");
else
if (num == (cache0+1))
printf("Hit at :1\n");
else
printf("Hit at %lu\n", 2 + num - cache1);
}
}
else
{ if (DebugCache)
{ if (DoCache && num <= (Stuff.Info.End - 2))
printf("Do Cache (miss %ld %ld)\n", num-cache0, num-cache1);
else
printf("Non Cache (miss %ld %ld)\n", num-cache0, num-cache1);
}
if (StatCache)
MicSta = IBASE->Micros;
if (DoCache && num <= (Stuff.Info.End - 2)) /* Must read 3 Blocks! */
{ cache0 = num;
cache1 = num + 2;
cache2 = num + Cache - 1;
if (cache2 > Stuff.Info.End)
cache2 = Stuff.Info.End;
ret = DevRead(num, *buf, BLOCK_SIZE*(1 + cache2 - cache0));
if (ret)
cache0 = cache1 = cache2 = CACHE_INVALID;
}
else
{ if (num != Stuff.Info.End)
cache0 = num;
else
{ cache0 = num - 1;
*buf = (ulong *)&Buffer[BLOCK_SIZE];
}
ret = DevRead(num, (ulong *)Buffer, BLOCK_SIZE*2);
if (ret)
cache0 = CACHE_INVALID;
}
if (StatCache)
MicFin = IBASE->Micros;
if (StatCache)
{ if (DoCache && num <= (Stuff.Info.End - 2))
{ ReadLarge++;
ReadLNum += (1 + cache2 - cache0);
}
else
ReadSmall++;
if (MicSta > MicFin)
MicFin += 1000000;
MicRead += (MicFin - MicSta);
}
}
}
DBGS("<CR");
return(ret);
}
Static char *StrType(type)
REG ushort type;
{
REG char *ans;
switch(type)
{
case I_ROOT:
ans = StrRoot;
break;
case I_DIR:
ans = StrDir;
break;
case I_FIL:
ans = StrFil;
break;
case I_EXT:
ans = StrExt;
break;
case I_DAT:
ans = StrDat;
break;
case I_S_LNK:
ans = StrSoftLnk;
break;
case I_H_LNK_DIR:
ans = StrDirLnk;
break;
case I_H_LNK_FIL:
ans = StrFilLnk;
break;
/*
case I_UNK:
case I_UNREADABLE:
*/
default:
ans = StrHuh;
break;
}
return(ans);
}
Static int BaD = 0;
Static int WaR = 0;
Static ulong SeqNum;
Static ulong PrevD = 0;
Static ulong NextD = 0;
#define B_TYP 0
#define B_KEY 1
#define B_CHKSUM 2
#define B_BMAP 3
#define B_PAR 4
#define B_COUNT 5
#define B_FIRST 6
#define B_BYTESIZE 7
#define B_HED 8
#define B_RANGE 9
#define B_SEQ 10
#define B_SHORT 11
#define B_BMFLG 12
#define B_HTSIZ 13
#define B_BITMAP 14
#define B_NEXTD 15
#define B_BADNAME 16
#define B_UNR 17
#define B_BLOCKSIZE 18
#define B_USED 19
#define B_USEDBY 20
#define B_PREVLINK 22
#define B_NEXTLINK 23
#define B_OFSLINK 24
#define B_NOPREVLINK 25
#define B_PREVINV 26
#define B_NOTPREV 27
#define B_PREVDIF 28
#define B_LINKTYPERR 29
#define B_XNOTLINK 30
Static bad(Rem, num, err, typ, ex1, ex2, ex3)
struct Info *Rem;
REG ulong num;
int err;
REG char *typ;
REG ulong ex1;
ulong ex2;
ulong ex3;
{
int idx;
ulong blk;
REG struct Info *CurRem;
REG struct Names *CurName;
ulong *Buf = (ulong *)Buffer;
int seeked = 0;
DBGS(">b");
switch(err)
{
case B_BMFLG:
case B_BITMAP:
case B_HTSIZ:
case B_BMAP:
case B_BLOCKSIZE:
case B_BYTESIZE:
case B_OFSLINK:
WaR++;
printf("War: B %lu %s ", num, typ);
break;
default:
BaD++;
printf("Err: B %lu %s ", num, typ);
break;
}
if (Rem && DosNames && num != Stuff.Info.Root)
{ CurRem = LastInfo;
if (Seek)
idx = CurRem - InfoList;
else
for (idx=0; CurRem != &InfoList[Stuff.Info.Root]; idx++)
CurRem = &InfoList[CurRem->Obj.dir->parent];
/* *** parent in same pos */
CurName = &RootName;
while (idx--)
{ if (CurName->next == (struct Names *)NULL)
{
DEBUGMEM_NAME("A CurName");
ZAlloc(CurName->next);
CurName->next->prev = CurName;
CurName->next->next = (struct Names *)NULL;
CurName->next->block = ULONGMAX;
}
CurName = CurName->next;
}
if (CurName->next)
CurName->next->block = ULONGMAX;
CurRem = LastInfo;
blk = LastBlk;
while (CurName)
{ if (CurName->block != blk)
{ CurName->block = blk;
if (!Seek && !seeked)
{ AkMotorOn(&Stuff);
seeked = !0;
}
if (CacheRead(blk + Stuff.Info.Begin, &Buf))
FName = (uchar *)"\011***Bad***";
else
FName = (uchar *)(&Buf[POS_NAME]);
if (*FName >= sizeof(RootName.name))
*FName = sizeof(RootName.name) - 1;
Copy(CurName->name, FName, (long)((*FName) + 1), sizeof(char));
}
if (Seek)
blk = (CurRem--)->Obj.dir->parent;
/* *** parent in same pos, blk not used if Root */
else
blk = InfoList[blk].Obj.dir->parent;
/* *** parent in same pos, blk not used if Root */
CurName = CurName->prev;
}
if (seeked)
AkMotorOff(&Stuff);
CurName = &RootName;
while (CurName && CurName->block != ULONGMAX)
{ if (CurName->prev)
{ if (CurName->prev == &RootName)
putchar(':');
else
putchar('/');
}
if (*CurName->name)
printf("%.*s", (int)(*(CurName->name)), (CurName->name)+1);
CurName = CurName->next;
}
putchar(' ');
}
switch(err)
{
case B_TYP:
printf("Block type wrong (par = %lu)", ex1);
break;
case B_KEY:
printf("Key wrong (par = %lu)", ex1);
break;
case B_CHKSUM:
printf("Checksum wrong (par = %lu)", ex1);
break;
case B_BMAP:
printf("No Bitmap blocks present!");
break;
case B_PAR:
printf("Parent pointer (%lu) != parent block (%lu)", ex1, ex2);
break;
case B_COUNT:
printf("Block Count incorrect (par = %lu)", ex1);
break;
case B_FIRST:
printf("FirstData incorrect (should be = %lu)", ex1);
break;
case B_BYTESIZE:
printf("Bytesize incorrect (calc = %lu actual = %lu)", ex1, ex2);
break;
case B_HED:
printf("Header pointer (%lu) != header block (%lu)", ex1, ex2);
break;
case B_RANGE:
printf("%s pointer (%lu) out of disk range!", ex1, ex2);
break;
case B_SEQ:
printf("Sequence number wrong (should be %lu, is %lu)", ex1, ex2);
break;
case B_SHORT:
printf("Data block not full (only allowed in last data block!)");
break;
case B_BMFLG:
printf("Bitmap Flag says Bitmap is invalid!");
break;
case B_HTSIZ:
printf("Hash table size != calculated size!");
break;
case B_BITMAP:
printf("Block type NOT unknown type!");
break;
case B_NEXTD:
printf("Next data block (%lu) != Previous data block's (%lu) Next data block (%lu)",
ex1, ex2, ex3);
break;
case B_BADNAME:
printf("Blocks name is invalid (BSTR size is 0 or > %d)", sizeof(RootName.name) - 1);
break;
case B_UNR:
printf("Gave error (0x%lx) on read (par = %lu)", ex1, ex2);
break;
case B_BLOCKSIZE:
printf("Total blocks incorrect (calc = %lu actual = %lu)", ex1, ex2);
break;
case B_USED:
if (ex1)
printf("Pointed to by %lu ", ex1);
printf("Already used (FFS Error)");
break;
case B_USEDBY:
printf("Pointed to by %lu Already used by %lu (FFS Error)", ex1, ex2);
break;
case B_PREVLINK:
printf("Prev Link Pointer not 0");
break;
case B_NEXTLINK:
printf("Next Link Pointer not 0");
break;
case B_OFSLINK:
printf("Contains a link (but partition is OFS)");
break;
case B_NOPREVLINK:
printf("Prev Link Pointer should not be 0");
break;
case B_PREVINV:
printf("Prev (%lu) Must be Fil or Dir (not %s)", ex1, ex2);
break;
case B_NOTPREV:
printf("Next's (%lu) Prev (%lu) should be This", ex1, ex2);
break;
case B_PREVDIF:
printf("Next's (%lu) Prev (%lu) != This Prev (%lu)", ex3, ex2, ex1);
break;
case B_LINKTYPERR:
printf("%s Pointer's type (%s) not valid for this type", ex1, ex2);
break;
case B_XNOTLINK:
printf("%s (%lu) is not Linked", ex1, ex2);
break;
}
putchar('\n');
if (ErrLimit >= 0 && BaD > ErrLimit)
{ printf("Validation aborted ... Error Limit (%ld) Exceeded\n", ErrLimit);
Cleanup();
}
if (WarnLimit >= 0 && WaR > WarnLimit)
{ printf("Validation aborted ... Warning Limit (%ld) Exceeded\n", WarnLimit);
Cleanup();
}
DBGS("<b");
}
Static CompareLinkType(prev_is_head, prev, next)
REG int prev_is_head;
REG ushort prev;
REG ushort next;
{
int ret = FALSE;
if (!prev_is_head)
{ if (prev == I_H_LNK_DIR && next == I_H_LNK_DIR)
ret = TRUE;
if (prev == I_H_LNK_FIL && next == I_H_LNK_FIL)
ret = TRUE;
}
else
{ if (prev == I_DIR && next == I_H_LNK_DIR)
ret = TRUE;
if (prev == I_FIL && next == I_H_LNK_FIL)
ret = TRUE;
}
return(ret);
}
/* OK this is really quite slow - but I don't have many links! */
Static CheckLinks()
{
REG struct Links *LinkTmp;
REG struct Links *LinkTmp2;
REG ulong next;
REG ulong prev;
REG ulong block;
ushort type;
int got_prev;
int got_next;
LinkTmp = LinkHead;
while (LinkTmp)
{ next = LinkTmp->next;
prev = LinkTmp->prev;
block = LinkTmp->block;
type = LinkTmp->type;
got_prev = !prev;
got_next = !next;
LinkTmp2 = LinkHead;
while (LinkTmp2)
{ if (prev && prev == LinkTmp2->block)
{ got_prev = !0;
if (LinkTmp2->type != I_DIR && LinkTmp2->type != I_FIL)
bad(NULL, block, B_PREVINV, StrType(type), prev, StrType(LinkTmp2->type));
if (!CompareLinkType(!0, LinkTmp2->type, type))
bad(NULL, block, B_LINKTYPERR, StrType(type), StrPrev, StrType(LinkTmp2->type));
}
if (next && next == LinkTmp2->block)
{ got_next = !0;
if (!prev && LinkTmp2->prev != block)
bad(NULL, block, B_NOTPREV, StrType(type), next, LinkTmp2->prev);
if (prev && LinkTmp2->prev != prev)
bad(NULL, block, B_PREVDIF, StrType(type), prev, LinkTmp2->prev, next);
if (!CompareLinkType(prev == 0, type, LinkTmp2->type))
bad(NULL, block, B_LINKTYPERR, StrType(type), StrNext, StrType(LinkTmp2->type));
}
LinkTmp2 = LinkTmp2->another;
}
if (!got_prev)
bad(NULL, block, B_XNOTLINK, StrType(type), StrPrev, prev);
if (!got_next)
bad(NULL, block, B_XNOTLINK, StrType(type), StrNext, next);
LinkTmp = LinkTmp->another;
}
}
Static MoveMaybe(block)
REG ulong block;
{
REG struct Links *LinkTmpPrev = NULL;
REG struct Links *LinkTmp = LinkMaybe;
while (LinkTmp && LinkTmp->block != block)
{ LinkTmpPrev = LinkTmp;
LinkTmp = LinkTmp->another;
}
if (LinkTmp)
{ if (LinkTmpPrev)
LinkTmpPrev->another = LinkTmp->another;
else
LinkMaybe = LinkTmp->another;
LinkTmp->another = LinkHead;
LinkHead = LinkTmp;
}
else
{ /* Huh? Shouldn't happen? */
MyError(ERR_NOVAL, "Link Code Bug");
}
}
Static AddLink(block, prev, next, type)
REG ulong block;
REG ulong prev;
REG ulong next;
REG ushort type;
{
struct Links *LinkTmp;
DBGS(">AL");
DEBUGMEM_NAME("A LinkTmp");
ZAlloc(LinkTmp);
LinkTmp->type = type;
LinkTmp->block = block - Stuff.Info.Begin;
LinkTmp->prev = prev;
LinkTmp->next = next;
LinkTmp->another = LinkMaybe;
LinkMaybe = LinkTmp;
DBGS("<AL");
}
Static getblok(num, Rem)
ulong num;
REG struct Info *Rem;
{
REG ulong *Buf;
REG uchar *obj;
REG ulong i;
REG ulong *l;
REG ulong *l2;
ulong count;
ushort *flags;
LONG ret;
ulong *buf;
DBGS(">gb");
if (ShowReads && (++ReadCount % Count) == 0)
{ akdeco(ReadCount, 'l', NULL, NULL, NULL, ' ', ' ');
akhexo(num, 'l', NULL, NULL, NULL, '\r', '0');
}
if (Tracks && (ReadCount++ % Stuff.Info.Cyl) == 0)
akdeco(ReadCount / Stuff.Info.Cyl, 'l', NULL, NULL, NULL, '\r', ' ');
ret = CacheRead(num, &buf);
if (!Seek)
Rem = &InfoList[num - Stuff.Info.Begin];
flags = &(Rem->flags);
*flags = 0;
if (ret)
{ Rem->type = I_UNREADABLE;
Rem->Obj.ret = ret;
DBGS("<gb");
return; /* N.B. */
}
Buf = buf;
switch(Buf[POS_TYP])
{
case TYP_CONTROL:
FName = (uchar *)(&Buf[POS_NAME]);
if (*FName == 0 || *FName >= sizeof(RootName.name))
*flags |= E_BADNAME;
switch(Buf[POS_SEC])
{
case SEC_ROOT:
Rem->type = I_ROOT;
if (Buf[POS_KEY])
*flags |= E_KEY;
/* Appears to be a date at POS_LINK_NEXT
if (Buf[POS_LINK_PREV])
*flags |= E_PREVLINK;
if (Buf[POS_LINK_NEXT])
*flags |= E_NEXTLINK;
*/
if (!Buf[POS_BMFLG])
*flags |= E_BMFLG;
if (Buf[POS_HTSIZ] != (1L + POS_LST_BLK - POS_FST_BLK))
*flags |= E_HTSIZ;
if (Seek)
(struct Root *)obj = Rem->Obj.root;
else
{
DEBUGMEM_NAME("Root");
ZAlloc((struct Root *)obj);
Rem->Obj.root = (struct Root *)obj;
}
for (count = 0, i = POS_FST_BLK, l = &Buf[i]; i <= POS_LST_BLK; l++, i++)
if (*l)
count++;
if (count++)
{
DEBUGMEM_NAME("Root Blk List");
LAlloc(l, count, StrRoot);
((struct Root *)obj)->blocks = l;
for (i = POS_FST_BLK, l2 = &Buf[i]; i <= POS_LST_BLK; l2++, i++)
if (*l2)
*(l++) = *l2;
*l = 0L;
}
else
((struct Root *)obj)->blocks = (ulong *)NULL;
for (i = POS_BBLK, l = &Buf[i]; *l && i < POS_BBLK_END; i++, l++)
;
count = i - POS_BBLK;
if (*l)
count++;
if (count)
{
DEBUGMEM_NAME("A BitMap Blk List");
LAlloc(l, count+1, StrBitMap);
Copy(l, &Buf[POS_BBLK], count, sizeof(ulong));
((struct Root *)obj)->bblocks = l;
l[count] = 0L;
}
else
((struct Root *)obj)->bblocks = (ulong *)NULL;
break;
case SEC_DIR:
Rem->type = I_DIR;
if (Buf[POS_KEY] != (num - Stuff.Info.Begin))
*flags |= E_KEY;
if (Buf[POS_LINK_PREV])
*flags |= E_PREVLINK;
if (Buf[POS_LINK_NEXT])
{ if (FileSystem == IS_OFS && !LinksAllowed)
*flags |= E_OFSLINK;
AddLink(num, 0L, Buf[POS_LINK_NEXT], I_DIR);
}
if (Seek)
(struct Dir *)obj = Rem->Obj.dir;
else
{
DEBUGMEM_NAME("A Dir");
ZAlloc((struct Dir *)obj);
Rem->Obj.dir = (struct Dir *)obj;
}
for (count = 0, i = POS_FST_BLK, l = &Buf[i]; i <= POS_LST_BLK; l++, i++)
if (*l)
count++;
if (count++)
{
DEBUGMEM_NAME("A Dir Blk List");
LAlloc(l, count, StrDir);
((struct Dir *)obj)->blocks = l;
for (i = POS_FST_BLK, l2 = &Buf[i]; i <= POS_LST_BLK; l2++, i++)
if (*l2)
*(l++) = *l2;
*l = 0L;
}
else
((struct Dir *)obj)->blocks = (ulong *)NULL;
((struct Dir *)obj)->chain = Buf[POS_HASH_CH];
((struct Dir *)obj)->parent = Buf[POS_PAR];
((struct Dir *)obj)->next = Buf[POS_LINK_NEXT];
break;
case SEC_FIL:
Rem->type = I_FIL;
if (Buf[POS_KEY] != (num - Stuff.Info.Begin))
*flags |= E_KEY;
if (Buf[POS_LINK_PREV])
*flags |= E_PREVLINK;
if (Buf[POS_LINK_NEXT])
{ if (FileSystem == IS_OFS && !LinksAllowed)
*flags |= E_OFSLINK;
AddLink(num, 0L, Buf[POS_LINK_NEXT], I_FIL);
}
if (Seek)
(struct Fil *)obj = Rem->Obj.fil;
else
{
DEBUGMEM_NAME("A Fil");
ZAlloc((struct Fil *)obj);
Rem->Obj.fil = (struct Fil *)obj;
}
for (i=POS_LST_BLK, l = &Buf[i]; *l && i > POS_FST_BLK; i--, l--)
;
count = POS_LST_BLK - i;
if (*l)
count++;
else
l++;
if (count != Buf[POS_NUM_BLK])
*flags |= E_COUNT;
((struct Fil *)obj)->num = count;
if (count)
{ if (Buf[POS_FST_DAT] != Buf[POS_LST_BLK])
*flags |= E_FIRST;
DEBUGMEM_NAME("A Fil Blk List");
LAlloc(l2, count, StrFil);
Copy(l2, l, count, sizeof(ulong));
((struct Fil *)obj)->blocks = l2;
}
else
{ ((struct Fil *)obj)->blocks = (ulong *)NULL;
if (Buf[POS_FST_DAT])
*flags |= E_FIRST;
}
((struct Fil *)obj)->bytesize = Buf[POS_F_BYTSIZ];
((struct Fil *)obj)->chain = Buf[POS_HASH_CH];
((struct Fil *)obj)->parent = Buf[POS_PAR];
((struct Fil *)obj)->extension = Buf[POS_EXT];
((struct Fil *)obj)->next = Buf[POS_LINK_NEXT];
break;
case SEC_S_LNK:
Rem->type = I_S_LNK;
if (Buf[POS_KEY] != (num - Stuff.Info.Begin))
*flags |= E_KEY;
if (Buf[POS_LINK_PREV])
*flags |= E_PREVLINK;
if (Buf[POS_LINK_NEXT])
*flags |= E_NEXTLINK;
if (FileSystem == IS_OFS && !LinksAllowed)
*flags |= E_OFSLINK;
if (Seek)
(struct Lnk *)obj = Rem->Obj.lnk;
else
{
DEBUGMEM_NAME("A Lnk");
ZAlloc((struct Lnk *)obj);
Rem->Obj.lnk = (struct Lnk *)obj;
}
((struct Lnk *)obj)->chain = Buf[POS_HASH_CH];
((struct Lnk *)obj)->parent = Buf[POS_PAR];
break;
case SEC_H_LNK_DIR:
Rem->type = I_H_LNK_DIR;
if (Buf[POS_KEY] != (num - Stuff.Info.Begin))
*flags |= E_KEY;
if (!Buf[POS_LINK_PREV])
*flags |= E_PREVLINK;
if (FileSystem == IS_OFS && !LinksAllowed)
*flags |= E_OFSLINK;
AddLink(num, Buf[POS_LINK_PREV], Buf[POS_LINK_NEXT], I_H_LNK_DIR);
if (Seek)
(struct DirLnk *)obj = Rem->Obj.dirlnk;
else
{
DEBUGMEM_NAME("A DirLnk");
ZAlloc((struct DirLnk *)obj);
Rem->Obj.dirlnk = (struct DirLnk *)obj;
}
((struct DirLnk *)obj)->prev = Buf[POS_LINK_PREV];
((struct DirLnk *)obj)->next = Buf[POS_LINK_NEXT];
((struct DirLnk *)obj)->chain = Buf[POS_HASH_CH];
((struct DirLnk *)obj)->parent = Buf[POS_PAR];
break;
case SEC_H_LNK_FIL:
Rem->type = I_H_LNK_FIL;
if (Buf[POS_KEY] != (num - Stuff.Info.Begin))
*flags |= E_KEY;
if (!Buf[POS_LINK_PREV])
*flags |= E_PREVLINK;
if (FileSystem == IS_OFS && !LinksAllowed)
*flags |= E_OFSLINK;
AddLink(num, Buf[POS_LINK_PREV], Buf[POS_LINK_NEXT], I_H_LNK_FIL);
if (Seek)
(struct FilLnk *)obj = Rem->Obj.fillnk;
else
{
DEBUGMEM_NAME("A FilLnk");
ZAlloc((struct FilLnk *)obj);
Rem->Obj.fillnk = (struct FilLnk *)obj;
}
((struct FilLnk *)obj)->prev = Buf[POS_LINK_PREV];
((struct FilLnk *)obj)->next = Buf[POS_LINK_NEXT];
((struct FilLnk *)obj)->chain = Buf[POS_HASH_CH];
((struct FilLnk *)obj)->parent = Buf[POS_PAR];
break;
default:
Rem->type = I_UNK;
break;
}
break;
case TYP_EXT:
Rem->type = I_EXT;
if (Buf[POS_KEY] != (num - Stuff.Info.Begin))
*flags |= E_KEY;
if (Seek)
(struct Ext *)obj = Rem->Obj.ext;
else
{
DEBUGMEM_NAME("An Ext");
ZAlloc((struct Ext *)obj);
Rem->Obj.ext = (struct Ext *)obj;
}
if (Buf[POS_FST_DAT])
*flags |= E_FIRST;
for (i=POS_LST_BLK, l = &Buf[i]; *l && i > POS_FST_BLK; i--, l--)
;
count = POS_LST_BLK - i;
if (*l)
count++;
else
l++;
if (count != Buf[POS_NUM_BLK])
*flags |= E_COUNT;
((struct Ext *)obj)->num = count;
if (count)
{
DEBUGMEM_NAME("An Ext Blk List");
LAlloc(l2, count, StrExt);
Copy(l2, l, count, sizeof(ulong));
((struct Ext *)obj)->blocks = l2;
}
else
((struct Ext *)obj)->blocks = (ulong *)NULL;
((struct Ext *)obj)->parent = Buf[POS_PAR];
((struct Ext *)obj)->extension = Buf[POS_EXT];
break;
case TYP_DAT:
Rem->type = I_DAT;
if (Seek)
(struct Dat *)obj = Rem->Obj.dat;
else
{
DEBUGMEM_NAME("A Dat");
ZAlloc((struct Dat *)obj);
Rem->Obj.dat = (struct Dat *)obj;
}
((struct Dat *)obj)->key = Buf[POS_KEY];
((struct Dat *)obj)->seqnum = Buf[POS_D_SEQ_NUM];
((struct Dat *)obj)->size = Buf[POS_D_DAT_SIZ];
((struct Dat *)obj)->nextd = Buf[POS_D_NXT_DAT];
if (((struct Dat *)obj)->nextd)
if (((struct Dat *)obj)->size != (BLOCK_SIZE - (POS_FST_BLK << 2L)))
*flags |= E_SHORT;
break;
default:
Rem->type = I_UNK;
break;
}
if (Rem->type != I_UNK && (Rem->type != I_DAT || FileSystem == IS_OFS))
if (DosChecksum(Buf))
*flags |= E_CHKSUM;
DBGS("<gb");
}
Static rchk(Rem, num, blk, typ, want)
REG struct Info *Rem;
REG ulong num;
REG ulong blk;
REG char *typ;
REG char *want;
{
if (blk < Stuff.Info.res || blk > (Stuff.Info.End - Stuff.Info.Begin))
{ bad(Rem, num, B_RANGE, typ, want, blk);
return(0);
}
return(!0);
}
Static int unreadable(Rem, num, Str, par)
REG struct Info *Rem;
REG ulong num;
REG char *Str;
REG ulong par;
{
if (Rem->type == I_UNREADABLE)
{ bad(Rem, num, B_UNR, Str, Rem->Obj.ret, par);
return(!0);
}
else
return(0);
}
Static FreeSeek(Rem)
REG struct Info *Rem;
{
REG ulong *l;
REG ulong count;
DBGS(">FS");
if (Seek)
switch(Rem->type)
{
case I_ROOT:
l = Rem->Obj.root->bblocks;
if (l)
{ for (count = 1; *l; l++, count++)
;
FreeMem(Rem->Obj.root->bblocks, ULONGS(count));
}
l = Rem->Obj.root->blocks;
if (l)
{ for (count = 1; *l; l++, count++)
;
FreeMem(Rem->Obj.root->blocks, ULONGS(count));
}
break;
case I_DIR:
l = Rem->Obj.dir->blocks;
if (l)
{ for (count = 1; *l; l++, count++)
;
FreeMem(Rem->Obj.dir->blocks, ULONGS(count));
}
break;
case I_FIL:
if (Rem->Obj.fil->blocks)
FreeMem(Rem->Obj.fil->blocks, ULONGS(Rem->Obj.fil->num));
break;
case I_EXT:
if (Rem->Obj.ext->blocks)
FreeMem(Rem->Obj.ext->blocks, ULONGS(Rem->Obj.ext->num));
break;
/*
case I_DAT:
case I_S_LNK:
case I_H_LNK_DIR:
case I_H_LNK_FIL:
*/
default:
break;
}
DBGS("<FS");
}
Static CheckUsed(num, Rem, str, par)
REG ulong num;
REG struct Info *Rem;
REG char *str;
REG ulong par;
{
if (FileSystem == IS_FFS)
if (Seek)
{ if (BMAP_TST(num))
bad(Rem, num, B_USED, str, par);
else
BMAP_SET(num);
}
else
{ if (Rem->flags & I_USED)
switch(Rem->type)
{
case I_DAT: /* well maybe? ;-) */
bad(Rem, num, B_USEDBY, str, par, Rem->Obj.dat->key);
break;
case I_DIR:
case I_FIL:
case I_EXT:
case I_S_LNK:
case I_H_LNK_DIR:
case I_H_LNK_FIL:
bad(Rem, num, B_USEDBY, str, par, Rem->Obj.dir->parent);
break;
/* Usually FFS Data Block
case I_ROOT:
case I_UNK:
case I_UNREADABLE:
*/
default:
bad(Rem, num, B_USED, str, par);
break;
}
else
Rem->flags |= I_USED;
}
}
Static long ChkDat(num, hed, Rem, key)
REG ulong num;
REG ulong hed;
REG struct Info *Rem;
REG ulong key;
{
REG ulong *l;
DoCache = !0;
if (Seek)
Get(Rem, num);
else
Rem = &InfoList[num];
CheckUsed(num, Rem, StrDat, key);
if (unreadable(Rem, num, StrDat, hed))
return(0);
if (FileSystem == IS_FFS)
{ FreeSeek(Rem);
return(1);
}
PrevD = num;
NextD = ULONGMAX;
SeqNum++;
if (Rem->type != I_DAT)
{ bad(Rem, num, B_TYP, StrDat, hed);
if (Rem->flags & E_CHKSUM)
bad(Rem, num, B_CHKSUM, StrDat, hed);
FreeSeek(Rem);
return(0);
}
else
{ if (Rem->Obj.dat->key != hed)
bad(Rem, num, B_HED, StrDat, Rem->Obj.dat->key, hed);
if (Rem->flags & E_CHKSUM)
bad(Rem, num, B_CHKSUM, StrDat, hed);
if (Rem->Obj.dat->seqnum != SeqNum)
bad(Rem, num, B_SEQ, StrDat, SeqNum, Rem->Obj.dat->seqnum);
if (Rem->flags & E_SHORT)
bad(Rem, num, B_SHORT, StrDat);
NextD = Rem->Obj.dat->nextd;
if (NextD)
rchk(Rem, num, NextD, StrDat, StrNextD);
FreeSeek(Rem);
return(Rem->Obj.dat->size);
}
}
Static long ChkExt(num, par, Rem)
ulong num;
ulong par;
REG struct Info *Rem;
{
REG ulong *l;
REG ulong *l2;
REG ulong bytesize = 0;
REG int oBaD = BaD;
DoCache = 0;
if (Seek)
Get(Rem, num);
else
Rem = &InfoList[num];
CheckUsed(num, Rem, StrExt, par);
if (unreadable(Rem, num, StrExt, par))
return(0);
if (Rem->type != I_EXT)
bad(Rem, num, B_TYP, StrExt, par);
else
if (Rem->Obj.ext->parent != par)
bad(Rem, num, B_PAR, StrExt, Rem->Obj.ext->parent, par);
if (Rem->flags & E_KEY)
bad(Rem, num, B_KEY, StrExt, par);
if (Rem->flags & E_CHKSUM)
bad(Rem, num, B_CHKSUM, StrExt, par);
if (Rem->flags & E_COUNT)
bad(Rem, num, B_COUNT, StrExt, par);
if (Rem->flags & E_FIRST)
bad(Rem, num, B_FIRST, StrExt, 0L);
if (IgnoreErr || BaD == oBaD)
{ l = Rem->Obj.ext->blocks;
if (l)
{ for (l2 = &l[Rem->Obj.ext->num - 1]; l2 >= l; l2--)
if (rchk(Rem, num, *l2, StrExt, StrDat))
{ if (FileSystem == IS_OFS && NextD != *l2 && NextD != ULONGMAX)
bad(Rem, num, B_NEXTD, StrExt, *l2, PrevD, NextD);
bytesize += ChkDat(*l2, par, Rem+1, num);
}
FreeSeek(Rem);
if (Rem->Obj.ext->extension && rchk(Rem, num, Rem->Obj.ext->extension, StrExt, StrExt))
bytesize += ChkExt(Rem->Obj.ext->extension, par, Rem);
/* Same Level (and don't need Rem anymore) */
}
else
FreeSeek(Rem);
}
else
FreeSeek(Rem);
return(bytesize);
}
Static ChkFil(num, par, Rem)
ulong num;
ulong par;
REG struct Info *Rem;
{
REG ulong *l;
REG ulong *l2;
REG ulong bytesize = 0;
REG int oBaD = BaD;
int flag = 0;
struct Info *oLastInfo = LastInfo;
ulong oLastBlk = LastBlk;
LastInfo = Rem;
LastBlk = num;
if (Rem->flags & E_KEY)
bad(Rem, num, B_KEY, StrFil, par);
if (Rem->flags & E_CHKSUM)
bad(Rem, num, B_CHKSUM, StrFil, par);
if (Rem->flags & E_COUNT)
bad(Rem, num, B_COUNT, StrFil, par);
if (Rem->flags & E_FIRST)
{ if (Rem->Obj.fil->blocks)
bad(Rem, num, B_FIRST, StrFil, Rem->Obj.fil->blocks[Rem->Obj.fil->num - 1]);
else
bad(Rem, num, B_FIRST, StrFil, 0L);
}
if (Rem->flags & E_BADNAME)
bad(Rem, num, B_BADNAME, StrFil);
if (Rem->flags & E_PREVLINK)
bad(Rem, num, B_PREVLINK, StrFil);
if (Rem->flags & E_OFSLINK)
bad(Rem, num, B_OFSLINK, StrFil);
if (Rem->Obj.fil->parent != par)
bad(Rem, num, B_PAR, StrFil, Rem->Obj.fil->parent, par);
if (Rem->Obj.fil->next)
{ rchk(Rem, num, Rem->Obj.fil->next, StrFil, StrNext);
MoveMaybe(num);
}
if (IgnoreErr || BaD == oBaD)
{ SeqNum = 0L;
l = Rem->Obj.fil->blocks;
if (l)
{ for(l2 = &l[Rem->Obj.fil->num - 1]; l2 >= l; l2--)
if (rchk(Rem, num, *l2, StrFil, StrDat))
{ if (flag)
{ if (FileSystem == IS_OFS && NextD != *l2 && NextD != ULONGMAX)
bad(Rem, num, B_NEXTD, StrFil, *l2, PrevD, NextD);
}
else
flag = !0;
bytesize += ChkDat(*l2, num, Rem+1, num);
}
if (Rem->Obj.fil->extension && rchk(Rem, num, Rem->Obj.fil->extension, StrFil, StrExt))
bytesize += ChkExt(Rem->Obj.fil->extension, num, Rem+1);
if (FileSystem == IS_OFS && NextD && NextD != ULONGMAX)
bad(Rem, num, B_NEXTD, StrFil, 0L, PrevD, NextD);
if (FileSystem == IS_OFS)
if (bytesize != Rem->Obj.fil->bytesize)
bad(Rem, num, B_BYTESIZE, StrFil, bytesize, Rem->Obj.fil->bytesize);
if (FileSystem == IS_FFS)
{ Rem->Obj.fil->bytesize += 511;
Rem->Obj.fil->bytesize /= 512; /* Calculate number of blocks - any other check available ???? */
if (bytesize != Rem->Obj.fil->bytesize)
bad(Rem, num, B_BLOCKSIZE, StrFil, bytesize, Rem->Obj.fil->bytesize);
}
}
LastInfo = oLastInfo;
LastBlk = oLastBlk;
FreeSeek(Rem);
if (Rem->Obj.fil->chain && rchk(Rem, num, Rem->Obj.fil->chain, StrFil, StrChain))
ChkEtc(Rem->Obj.fil->chain, par, Rem);
/* Same Level (and don't need Rem anymore) */
}
else
{ LastInfo = oLastInfo;
LastBlk = oLastBlk;
FreeSeek(Rem);
}
}
Static ChkDir(num, par, Rem)
REG ulong num;
REG ulong par;
REG struct Info *Rem;
{
REG ulong *l;
REG int oBaD = BaD;
struct Info *oLastInfo = LastInfo;
ulong oLastBlk = LastBlk;
LastInfo = Rem;
LastBlk = num;
if (Rem->flags & E_KEY)
bad(Rem, num, B_KEY, StrDir, par);
if (Rem->flags & E_CHKSUM)
bad(Rem, num, B_CHKSUM, StrDir, par);
if (Rem->flags & E_BADNAME)
bad(Rem, num, B_BADNAME, StrDir);
if (Rem->flags & E_PREVLINK)
bad(Rem, num, B_PREVLINK, StrDir);
if (Rem->flags & E_OFSLINK)
bad(Rem, num, B_OFSLINK, StrDir);
if (Rem->Obj.dir->parent != par)
bad(Rem, num, B_PAR, StrDir, Rem->Obj.dir->parent, par);
if (Rem->Obj.dir->next)
{ rchk(Rem, num, Rem->Obj.dir->next, StrDir, StrNext);
MoveMaybe(num);
}
if (IgnoreErr || BaD == oBaD)
{ l = Rem->Obj.dir->blocks;
if (l)
for (; *l; l++)
if (rchk(Rem, num, *l, StrDir, StrEtc))
ChkEtc(*l, num, Rem+1);
LastInfo = oLastInfo;
LastBlk = oLastBlk;
FreeSeek(Rem);
if (Rem->Obj.dir->chain && rchk(Rem, num, Rem->Obj.dir->chain, StrDir, StrChain))
ChkEtc(Rem->Obj.dir->chain, par, Rem);
/* Same Level (and don't need Rem anymore) */
}
else
{ LastInfo = oLastInfo;
LastBlk = oLastBlk;
FreeSeek(Rem);
}
}
Static ChkLnk(num, par, Rem)
REG ulong num;
REG ulong par;
REG struct Info *Rem;
{
REG ulong *l;
REG int oBaD = BaD;
struct Info *oLastInfo = LastInfo;
ulong oLastBlk = LastBlk;
LastInfo = Rem;
LastBlk = num;
if (Rem->flags & E_KEY)
bad(Rem, num, B_KEY, StrSoftLnk, par);
if (Rem->flags & E_CHKSUM)
bad(Rem, num, B_CHKSUM, StrSoftLnk, par);
if (Rem->flags & E_BADNAME)
bad(Rem, num, B_BADNAME, StrSoftLnk);
if (Rem->flags & E_PREVLINK)
bad(Rem, num, B_PREVLINK, StrRoot);
if (Rem->flags & E_NEXTLINK)
bad(Rem, num, B_NEXTLINK, StrRoot);
if (Rem->flags & E_OFSLINK)
bad(Rem, num, B_OFSLINK, StrSoftLnk);
if (Rem->Obj.lnk->parent != par)
bad(Rem, num, B_PAR, StrSoftLnk, Rem->Obj.lnk->parent, par);
LastInfo = oLastInfo;
LastBlk = oLastBlk;
FreeSeek(Rem);
if (IgnoreErr || BaD == oBaD)
{ if (Rem->Obj.lnk->chain && rchk(Rem, num, Rem->Obj.lnk->chain, StrSoftLnk, StrChain))
ChkEtc(Rem->Obj.lnk->chain, par, Rem);
/* Same Level (and don't need Rem anymore) */
}
}
Static ChkDirLnk(num, par, Rem)
REG ulong num;
REG ulong par;
REG struct Info *Rem;
{
REG ulong *l;
REG int oBaD = BaD;
struct Info *oLastInfo = LastInfo;
ulong oLastBlk = LastBlk;
LastInfo = Rem;
LastBlk = num;
if (Rem->flags & E_KEY)
bad(Rem, num, B_KEY, StrDirLnk, par);
if (Rem->flags & E_CHKSUM)
bad(Rem, num, B_CHKSUM, StrDirLnk, par);
if (Rem->flags & E_BADNAME)
bad(Rem, num, B_BADNAME, StrDirLnk);
if (Rem->flags & E_PREVLINK)
bad(Rem, num, B_NOPREVLINK, StrDirLnk);
if (Rem->flags & E_OFSLINK)
bad(Rem, num, B_OFSLINK, StrDirLnk);
if (Rem->Obj.dirlnk->parent != par)
bad(Rem, num, B_PAR, StrDirLnk, Rem->Obj.dirlnk->parent, par);
if (Rem->Obj.dirlnk->prev)
rchk(Rem, num, Rem->Obj.dirlnk->prev, StrDirLnk, StrPrev);
if (Rem->Obj.dirlnk->next)
rchk(Rem, num, Rem->Obj.dirlnk->next, StrDirLnk, StrNext);
MoveMaybe(num);
LastInfo = oLastInfo;
LastBlk = oLastBlk;
FreeSeek(Rem);
if (IgnoreErr || BaD == oBaD)
{ if (Rem->Obj.dirlnk->chain && rchk(Rem, num, Rem->Obj.dirlnk->chain, StrDirLnk, StrChain))
ChkEtc(Rem->Obj.dirlnk->chain, par, Rem);
/* Same Level (and don't need Rem anymore) */
}
}
Static ChkFilLnk(num, par, Rem)
REG ulong num;
REG ulong par;
REG struct Info *Rem;
{
REG ulong *l;
REG int oBaD = BaD;
struct Info *oLastInfo = LastInfo;
ulong oLastBlk = LastBlk;
LastInfo = Rem;
LastBlk = num;
if (Rem->flags & E_KEY)
bad(Rem, num, B_KEY, StrFilLnk, par);
if (Rem->flags & E_CHKSUM)
bad(Rem, num, B_CHKSUM, StrFilLnk, par);
if (Rem->flags & E_BADNAME)
bad(Rem, num, B_BADNAME, StrFilLnk);
if (Rem->flags & E_PREVLINK)
bad(Rem, num, B_NOPREVLINK, StrFilLnk);
if (Rem->flags & E_OFSLINK)
bad(Rem, num, B_OFSLINK, StrFilLnk);
if (Rem->Obj.fillnk->parent != par)
bad(Rem, num, B_PAR, StrFilLnk, Rem->Obj.fillnk->parent, par);
if (Rem->Obj.fillnk->prev)
rchk(Rem, num, Rem->Obj.fillnk->prev, StrFilLnk, StrPrev);
if (Rem->Obj.fillnk->next)
rchk(Rem, num, Rem->Obj.fillnk->next, StrFilLnk, StrNext);
MoveMaybe(num);
LastInfo = oLastInfo;
LastBlk = oLastBlk;
FreeSeek(Rem);
if (IgnoreErr || BaD == oBaD)
{ if (Rem->Obj.fillnk->chain && rchk(Rem, num, Rem->Obj.fillnk->chain, StrFilLnk, StrChain))
ChkEtc(Rem->Obj.fillnk->chain, par, Rem);
/* Same Level (and don't need Rem anymore) */
}
}
Static ChkEtc(num, par, Rem)
REG ulong num;
REG ulong par;
REG struct Info *Rem;
{
REG ulong *l;
DoCache = 0;
if (Seek)
Get(Rem, num);
else
Rem = &InfoList[num];
CheckUsed(num, Rem, StrEtc, par);
if (unreadable(Rem, num, StrEtc, par))
return;
switch(Rem->type)
{
case I_DIR:
ChkDir(num, par, Rem);
break;
case I_FIL:
ChkFil(num, par, Rem);
break;
case I_S_LNK:
ChkLnk(num, par, Rem);
break;
case I_H_LNK_DIR:
ChkDirLnk(num, par, Rem);
break;
case I_H_LNK_FIL:
ChkFilLnk(num, par, Rem);
break;
default:
bad(Rem, num, B_TYP, StrEtc, par);
FreeSeek(Rem);
break;
}
}
Static ChkBMap(num, par, Rem)
REG ulong num;
REG ulong par;
REG struct Info *Rem;
{
DoCache = !0;
if (Seek)
Get(Rem, num);
else
Rem = &InfoList[num];
CheckUsed(num, Rem, StrBitMap, par);
if (unreadable(Rem, num, StrBitMap, par))
return;
if (Rem->flags & E_CHKSUM)
bad(Rem, num, B_CHKSUM, StrBitMap, par);
if (Rem->type != I_UNK)
bad(Rem, num, B_BITMAP, StrBitMap);
/* How do I test that this really is a bitmap block? Probably generate a warning */
FreeSeek(Rem);
}
Static ChkRoot(num, Rem)
REG ulong num;
REG struct Info *Rem;
{
REG ulong *l;
REG int oBaD = BaD;
DBGS(">ChkRoot");
if (Seek)
Get(Rem, num);
else
Rem = &InfoList[num];
LastInfo = Rem;
LastBlk = num;
CheckUsed(num, Rem, StrRoot, 0L);
if (unreadable(Rem, num, StrRoot, 0L))
return;
if (Rem->type != I_ROOT)
bad(Rem, num, B_TYP, StrRoot, 0L);
if (Rem->flags & E_BMFLG)
bad(Rem, num, B_BMFLG, StrRoot);
if (Rem->flags & E_HTSIZ)
bad(Rem, num, B_HTSIZ, StrRoot);
if (Rem->flags & E_KEY)
bad(Rem, num, B_KEY, StrRoot, 0L);
if (Rem->flags & E_CHKSUM)
bad(Rem, num, B_CHKSUM, StrRoot, 0L);
if (Rem->flags & E_BADNAME)
bad(Rem, num, B_BADNAME, StrRoot);
/* appears to be a date in NEXTLINK position
if (Rem->flags & E_PREVLINK)
bad(Rem, num, B_PREVLINK, StrRoot);
if (Rem->flags & E_NEXTLINK)
bad(Rem, num, B_NEXTLINK, StrRoot);
*/
if (IgnoreErr || BaD == oBaD)
{ l = Rem->Obj.root->bblocks;
if (!l)
bad(Rem, num, B_BMAP, NULL);
else
for (; *l; l++)
if (rchk(Rem, num, *l, StrRoot, StrBitMap))
ChkBMap(*l, num, Rem+1);
l = Rem->Obj.root->blocks;
if (l)
for (; *l; l++)
if (rchk(Rem, num, *l, StrRoot, StrEtc))
ChkEtc(*l, num, Rem+1);
}
FreeSeek(Rem);
DBGS("<ChkRoot");
}
Static ValidateIt()
{
REG ulong l;
REG ulong size;
REG ulong *bptr;
if (Seek)
size = MaxDepth;
else
size = 1L + Stuff.Info.End - Stuff.Info.Begin;
DEBUGMEM_NAME("InfoList");
MPAlloc(InfoList, (sizeof(*InfoList) * size), &GenPoolKey);
if (!Seek)
{ AkMotorOn(&Stuff);
DoCache = !0;
for (l = Stuff.Info.Begin; l <= Stuff.Info.End; l++)
getblok(l, NULL);
AkMotorOff(&Stuff);
ChkRoot(Stuff.Info.Root, NULL);
}
else
{ while (size-- > 0)
{
DEBUGMEM_NAME("An InfoList fil");
MPAlloc(InfoList[size].Obj.fil, sizeof(struct Fil), &GenPoolKey);
}
if (FileSystem == IS_FFS)
{ size = 1L + Stuff.Info.End - Stuff.Info.Begin;
DEBUGMEM_NAME("BitMap");
MPAlloc(MyBitMap, (size+7)/8, &ZerPoolKey);
}
AkMotorOn(&Stuff);
DoCache = !0;
ChkRoot(Stuff.Info.Root, InfoList);
AkMotorOff(&Stuff);
}
CheckLinks();
if (BaD || WaR)
printf("\nTotal Displayed errors for %s %d, Warnings: %d\n", Device, BaD, WaR);
else
printf("\nNo errors detected on %s\n", Device);
if (DebugLink)
{ puts("Links:");
if (!LinkHead)
puts("\tNone!");
else
{ while (LinkHead)
{ printf("\t%-10s Blk:%10lu Prev:%10lu Next:%10lu\n",
StrType(LinkHead->type),
LinkHead->block,
LinkHead->prev,
LinkHead->next);
LinkHead = LinkHead->another;
}
}
puts("Maybes: (but not!)");
if (!LinkMaybe)
puts("\tNone!");
else
{ while (LinkMaybe)
{ printf("\t%-10s Blk:%10lu Prev:%10lu Next:%10lu\n",
StrType(LinkMaybe->type),
LinkMaybe->block,
LinkMaybe->prev,
LinkMaybe->next);
LinkMaybe = LinkMaybe->another;
}
}
}
}
Static Val()
{
LONG ret;
ulong *buf;
if (Dev = AkDevOpen(Device, &Stuff))
MyError(Dev, Device);
if (Inhibit)
Inhibited = AkDevInhibit(&Stuff, -1L);
DEBUGMEM_NAME("Buffer");
MPAlloc(Buffer, (long)(BLOCK_SIZE*Cache), &BufPoolKey);
AkDevMsg(&(Stuff.Info));
if (Ffs || Ofs) /* Force FS choice */
{ if (Ofs)
FileSystem = IS_OFS;
else
FileSystem = IS_FFS;
}
else
{ if (ShowFileSystem)
printf("FileSystemHandler is \"%s\"\n", Stuff.Info.fsys);
printf("Boot Block File System ... ");
fflush(stdout);
FileSystem = IS_FFS; /* Assume - change if wrong */
AkMotorOn(&Stuff);
DoCache = !Seek;
ret = CacheRead(Stuff.Info.Begin, &buf);
AkMotorOff(&Stuff);
if (ret)
printf("Error 0x%lx on Read Block Zero - Assumed FFS\n", ret);
else
{ if ((*buf & 0xffffff00) != 0x444f5300)
printf("Doesn't appear to be DOS - Assumed FFS\n");
else
{ if ((*buf & 0xff) == 0)
{ FileSystem = IS_OFS;
printf("Appears to be OFS\n");
}
else
printf("Appears to be FFS or similar\n");
}
}
}
ValidateIt();
}
main(argc, argv)
int argc;
char *argv[];
{
REG int idx;
cli = argc;
DO_QUAL();
if (Cache > 1)
Cache += 2;
if (!Quiet && cli)
STARTUP_MSG;
OPEN_LIB(IBASE, "intuition.library", INTUITION_REV);
PoolInit(&BufPoolKey, 0L, MEMF_CHIP);
PoolInit(&GenPoolKey, PoolSize, 0L);
PoolInit(&ZerPoolKey, 0L, MEMF_CLEAR);
Val();
if (StatCache)
{ ulong BTot = ReadSmall*2 + ReadLNum;
ulong RTot = HitSmall + HitLarge + ReadSmall + ReadLarge;
#define PER(x) (RTot ? (double)(x) / (double)(RTot) * (double)(100): (double)0)
printf("Cache Statistics (Real Time) - Cache = 2:%d\n", Cache-2);
if (Cache == 1)
puts("Well ... first you need to HAVE a cache! (Try /cache=75)");
else
{ printf("Blocks Requested....... %10lu\n", RTot);
printf("Blocks Read............ %10lu\n", BTot);
printf("Average Reads/Request.. %10.2lf\n", (double)(BTot) / (double)(RTot));
printf("Total ╡secs Cache Code. %10lu\n", MicCode);
if (MicCode)
printf("Average ╡sec/CodeReq... %10.2lf\n",
(double)(MicCode) / (double)(HitSmall + HitLarge));
printf("Total ╡secs Cache IOReq %10lu\n", MicRead);
if (MicRead)
printf("Average ╡sec/IOReq..... %10.2lf\n",
(double)(MicRead) / (double)(ReadSmall + ReadLarge));
printf("Total ╡secs Cache Req.. %10lu\n", MicCode + MicRead);
if (MicCode || MicRead)
printf("Average ╡sec/Request... %10.2lf\n",
((double)(MicCode) + (double)(MicRead)) / (double)(RTot));
printf("Hits on Small Cache.... %10lu %6.2lf%%\n", HitSmall, PER(HitSmall));
printf("Hits on Large Cache.... %10lu %6.2lf%%\n", HitLarge, PER(HitLarge));
printf("Reads to Small Cache... %10lu %6.2lf%%\n", ReadSmall, PER(ReadSmall));
printf("Reads to Large Cache... %10lu %6.2lf%%\n", ReadLarge, PER(ReadLarge));
}
}
Cleanup();
}
MyError(num, why)
REG long num;
REG char *why;
{
ERROR_INIT
if (Inhibited)
AkDevInhibit(&Stuff, 0L);
if (!Dev)
AkDevClose(&Stuff);
ERROR_TEST
CASE_ERR_TOODEEP
CASE_ERR_AKDEVALL
CASE_ERR_NOVAL
CASE_ERR_NOMEM
CASE_ERR_NOLIB
CASE_ERR_BADFIL
ERROR_END(FACILITY_VAL)
PoolFree(&ZerPoolKey);
PoolFree(&GenPoolKey);
PoolFree(&BufPoolKey);
if (IBASE)
CloseLibrary(IBASE);
CLEANUP_QUAL();
ERROR_EXIT
}